package peerToPeerFacebook.proj;

import java.io.FileNotFoundException;
import java.io.Serializable;


/**
 * Implements IFileServerMethods
 */
public class FileServerMethods implements IFileServerMethods 
{
	private RemoteInvoker client;
	private int node;
	 private String format = "***************";
	
	public FileServerMethods(RemoteInvoker client, int node)
	{
		ArgumentValidator.IsNotNull("rpcClient", client);
		this.client = client;
		this.node = node;
	}

	/**
	 * helper method which prints the required error messages in case of call failures
	 * @param command: the command which failed
	 * @param serverID: the server ID on which it failed
	 * @param fileName: the filename on which the requested operatin failed
	 * @param status: the status of the call
	 * @param result: the result of the call
	 */
	private void handleFailure(String command, int serverID, String fileName, Status status, Serializable result)
  {
    if((status == Status.Exception) && (result instanceof RPCPacketTooBig))
    {
      System.out.println("\n\nNode " + this.node +": Error: " + command + " on server "+ serverID +" and file " + fileName + " returned error code 30 File too large\n\n");
      return;
    }
    
    if((status == Status.Exception) && (result instanceof FileAlreadyExistException))
    {
      System.out.println("\n\nNode " + this.node +": Error: " + command + " on server "+ serverID +" and file " + fileName + " returned error code 30 File already exists\n\n");
      return;
    }
    
    if((status == Status.Exception) && (result instanceof FileNotFoundException))
    {
      System.out.println("\n\nNode " + this.node +": Error: " + command + " on server "+ serverID +" and file " + fileName + " returned error code 10 File does not exist\n\n");
      return;
    }
    
    if((status == Status.Exception) && (result instanceof RPCTimeout))
    {
      System.out.println("\n\nNode " + this.node +": Error: " + command + " on server "+ serverID +" and file " + fileName + " returned error code 20 Timeout\n\n");
      return;
    } 
    else
    {
      System.out.println("\n\n Node " + this.node +": Error: " + command + " on server "+ serverID +" and file " + fileName + " returned " + result);
    }
  }
	
	/**
	 * Creates empty file on server
	 * @param serverID
	 * @param fileName
	 */
	public void create(final int serverID, final String fileName)
	{
		ArgumentValidator.IsNotNullOrEmpty("fileName", fileName);
		
		client.invoke(IServerFileIO.CreateFileMethodName, 
						 new Serializable[] { fileName  },
						 new IResultCallback()
						{
							public void resultCallback(Status status, Serializable result)
							{
							  if(status != Status.Success)
							  {
							    handleFailure("create", serverID, fileName, status, result);
							  }
							  else
							  {
								System.out.println("\n\n " + format + "Creation of "+ fileName +" succeeded" + format + "\n\n");
							  }
							}
						});		
	}

	/**
	 * Gets file contents from server, and prints them on console
	 * @param serverID
	 * @param fileName
	 * @return contents
	 */
	public void get(final int serverID, final String fileName)
	{
		ArgumentValidator.IsNotNullOrEmpty("fileName", fileName);
		
		client.invoke(IServerFileIO.GetFileContentsMethodName, 
						 new Serializable[] { fileName  },
						 new IResultCallback()
						{
							public void resultCallback(Status status, Serializable result)
							{
							  if(status != Status.Success)
                {
							    handleFailure("get", serverID, fileName, status, result);
                }
							  else
							  {
							    System.out.println("\n\n " + format + " The contents of the "+ fileName +" are: " + format + "\n" + result.toString());
							  }
									
							}
						});
	}
	
	/**
	 * Overwrite contents of file on server	 * 
	 * @param serverID
	 * @param fileName
	 * @param contents
	 */
	public void put(final int serverID, final String fileName, final String contents)
	{
		ArgumentValidator.IsNotNullOrEmpty("fileName", fileName);
		ArgumentValidator.IsNotNullOrEmpty("contents", contents);
		
		client.invoke(IServerFileIO.PutContentsToFileMethodName, 
						 new Serializable[] { fileName, contents },
						 new IResultCallback()
						{
							public void resultCallback(Status status, Serializable result)
							{
							  if(status != Status.Success)
                {
							    handleFailure("put", serverID, fileName, status, result);
                }
                else
                {
                  System.out.println("\n\n " + format + " The contents were succesfully added to the file: "+ fileName  + format );
                }
								
							}
						});		
	}
	
	/**
	 * Appends contents to file on server
	 * @param serverID
	 * @param fileName
	 * @param contents
	 */
	public void append(final int serverID, final String fileName, final String contents)
	{
		ArgumentValidator.IsNotNullOrEmpty("fileName", fileName);
		ArgumentValidator.IsNotNullOrEmpty("contents", contents);
		
		client.invoke(IServerFileIO.AppendContentsToFileMethodName, 
						 new Serializable[] { fileName, contents },
						 new IResultCallback()
						{
							public void resultCallback(Status status, Serializable result)
							{
							  if(status != Status.Success)
                {
							    handleFailure("append", serverID, fileName, status, result);
                }
                else
                {
                  System.out.println("\n\n " + format + " The contents were succesfully appended to the file: "+ fileName + format );
                }
								
							}
						});	
	}
	
	/**
	 * Deletes file on server
	 * @param serverID
	 * @param fileName
	 */
	public void delete(final int serverID, final String fileName)
	{
		ArgumentValidator.IsNotNullOrEmpty("fileName", fileName);
		
		client.invoke(IServerFileIO.DeleteFileMethodName, 
						 new Serializable[] { fileName  },
						 new IResultCallback()
						{
							public void resultCallback(Status status, Serializable result)
							{
							  if(status != Status.Success)
                {
							    handleFailure("delete", serverID, fileName, status, result);
                }
                else
                {
                  System.out.println(" \n\n " + format + "The file "+ fileName +" got deleted successfully  " + format + "\n\n");
                }	
							}
						});		
	}
}
